Monitors sensors in an industrial oven, indicates level alarms by changing colors, allows the user to change a setpoint, and logs the values into a CSV file.
The form:
// $Header: $ // Copyright (c) CODE Consulting and Development, s.r.o., Plzen. All rights reserved. // ReSharper disable CommentTypo // // Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html . // OPC client and subscriber examples in C# on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-CSharp . // Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own // a commercial license in order to use Online Forums, and we reply to every post. using System; using System.Diagnostics; using System.Drawing; using System.Globalization; using System.Windows.Forms; using JetBrains.Annotations; using OpcLabs.EasyOpc; using OpcLabs.EasyOpc.DataAccess; using OpcLabs.EasyOpc.DataAccess.OperationModel; using OpcLabs.EasyOpc.OperationModel; namespace OvenControl { public partial class Form1 : Form { private const string MachineName = ""; private const string ServerClass = "SWToolbox.TOPServer.V5"; // or "Kepware.KEPServerEX.V5" private DAVtq _fanPower; private DAVtq _heaterPower; private DAVtq _ovenTemperature; private DAVtq _heaterTemperature; private DAVtq _fanSpeed; private DAVtq _temperatureSetpoint; // ReSharper disable once NotNullMemberIsNotInitialized public Form1() { InitializeComponent(); } private Color _defaultBackColor = Color.White; // ReSharper disable InconsistentNaming private void Form1_Load(object sender, EventArgs e) // ReSharper restore InconsistentNaming { SetDefaults(); _defaultBackColor = txbOvenTemperature.BackColor; } private void SetDefaults() { nudUpdateRate.Value = 10; } // ReSharper disable InconsistentNaming private void btnStart_Click(object sender, EventArgs e) // ReSharper restore InconsistentNaming { btnStart.Enabled = false; timer1.Interval = Decimal.ToInt32(nudUpdateRate.Value * 1000); timer1.Start(); UpdateValuesAndLog(); btnStop.Enabled = true; } // ReSharper disable InconsistentNaming private void btnStop_Click(object sender, EventArgs e) // ReSharper restore InconsistentNaming { btnStop.Enabled = false; timer1.Stop(); btnStart.Enabled = true; } // ReSharper disable InconsistentNaming private void timer1_Tick(object sender, EventArgs e) // ReSharper restore InconsistentNaming { UpdateValuesAndLog(); } private static Int32? ConvertValueToInt32(DAVtq vtq) { if (vtq is null) return null; if (!vtq.HasValue) return null; return vtq.Value as Int32?; } private static string GetTextVtq(DAVtq vtq) { if ((vtq is null) || (!vtq.HasValue)) { return "???"; } return vtq.DisplayValue(); } private void DisplayVtq( DAVtq vtq, // ReSharper disable once SuggestBaseTypeForParameter TextBox txb, int colorTestId) { if ((vtq is null) || (!vtq.HasValue)) { // ReSharper disable LocalizableElement txb.Text = "???"; // ReSharper restore LocalizableElement txb.BackColor = Color.Magenta; } else { txb.Text = vtq.DisplayValue(); Int32? value; Color backColor = _defaultBackColor; switch (colorTestId) { case 0: txb.BackColor = _defaultBackColor; break; case 1: // oven temperature value = ConvertValueToInt32(vtq); if (value.HasValue) { Int32? range = ConvertValueToInt32(_temperatureSetpoint); if (range.HasValue) { if (value <= (range - 5)) backColor = Color.Blue; else if (value >= (range + 5)) backColor = Color.Red; } } txb.BackColor = backColor; break; case 2: // oven temperature value = ConvertValueToInt32(vtq); // ReSharper disable once UseNullPropagation if (value.HasValue) { if (value < 200) backColor = Color.Red; } txb.BackColor = backColor; break; } } } private DAVtq ReadVtq(string itemId) { DAVtq vtq; Exception exception = null; try { vtq = easyDAClient1.ReadItem(MachineName, ServerClass, itemId); } catch (OpcException ex) { exception = ex; vtq = null; } DisplayException(exception); return vtq; } private DAVtqResult[] ReadMultipleVtq(string[] itemIds) { DAVtqResult[] results; Exception exception = null; var itemDescriptors = new DAItemDescriptor[itemIds.Length]; for (int i = 0; i < itemIds.Length; i++) { Debug.Assert(itemIds[i] != null); itemDescriptors[i] = new DAItemDescriptor(itemIds[i]); } try { results = easyDAClient1.ReadMultipleItems(new ServerDescriptor(MachineName, ServerClass), itemDescriptors); } catch (OpcException ex) { exception = ex; results = null; } DisplayException(exception); return results; } private string _lastExceptionMessage = ""; private void DisplayException(Exception exception) { //txbExceptions.Text = (exception is null) ? "" : exception.GetBaseException().Message; if (!(exception is null)) { string newMessage = $"{DateTime.Now} {exception.GetBaseException().Message}"; if (_lastExceptionMessage != newMessage) { _lastExceptionMessage = newMessage; txbExceptions.AppendText(newMessage + Environment.NewLine); } } } private void ReadMultiple() { DAVtqResult[] results = ReadMultipleVtq(new[] { "Channel1.Device1.FanPower", "Channel1.Device1.FanSpeed", "Channel1.Device1.HeaterPower", "Channel1.Device1.HeaterTemp", "Channel1.Device1.TempSetPoint", "Channel1.Device1.OvenTemp" }); if (results is null) return; Debug.Assert(results[0] != null); Debug.Assert(results[1] != null); Debug.Assert(results[2] != null); Debug.Assert(results[3] != null); Debug.Assert(results[4] != null); Debug.Assert(results[5] != null); if (results[0].Exception is null) _fanPower = results[0].Vtq; else { _fanPower = null; DisplayException(results[0].Exception); } if (results[1].Exception is null) _fanSpeed = results[1].Vtq; else { _fanSpeed = null; DisplayException(results[1].Exception); } if (results[2].Exception is null) _heaterPower = results[2].Vtq; else { _heaterPower = null; DisplayException(results[2].Exception); } if (results[3].Exception is null) _heaterTemperature = results[3].Vtq; else { _heaterTemperature = null; DisplayException(results[3].Exception); } if (results[4].Exception is null) _temperatureSetpoint = results[4].Vtq; else { _temperatureSetpoint = null; DisplayException(results[4].Exception); } if (results[5].Exception is null) _ovenTemperature = results[5].Vtq; else { _ovenTemperature = null; DisplayException(results[5].Exception); } } private void UpdateValuesAndLog() { // read multiple item ReadMultiple(); DisplayVtq(_fanPower, txbFanPower, 0); DisplayVtq(_fanSpeed, txbFanSpeed, 0); DisplayVtq(_heaterPower, txbHeaterPower, 0); DisplayVtq(_heaterTemperature, txbHeaterTemperature, 2); DisplayVtq(_temperatureSetpoint, txbTemperatureSetpoint, 0); DisplayVtq(_ovenTemperature, txbOvenTemperature, 1); WriteToLog(); } // ReSharper disable InconsistentNaming private void btnSetTemperatureSetpoint_Click(object sender, EventArgs e) // ReSharper restore InconsistentNaming { object value = txbNewTemperatureSetpoint.Text; Exception exception = null; try { easyDAClient1.WriteItemValue( MachineName, ServerClass, "Channel1.Device1.TempSetPoint", value); } catch (OpcException ex) { exception = ex; } DisplayException(exception); _temperatureSetpoint = ReadVtq("Channel1.Device1.TempSetPoint"); DisplayVtq(_temperatureSetpoint, txbTemperatureSetpoint, 0); DisplayVtq(_ovenTemperature, txbOvenTemperature, 1); } private void WriteToLog() { try { var sw = new System.IO.StreamWriter(Application.StartupPath + "\\OvenControl.csv", true); sw.WriteLine( DateTime.Now.ToString(CultureInfo.InvariantCulture) + "," + GetTextVtq(_fanPower) + "," + GetTextVtq(_heaterPower) + "," + GetTextVtq(_ovenTemperature) + "," + GetTextVtq(_heaterTemperature) + "," + GetTextVtq(_fanSpeed) + "," + GetTextVtq(_temperatureSetpoint)); sw.Close(); } catch (Exception e) { DisplayException(e); } } // ReSharper disable InconsistentNaming private void btnClose_Click(object sender, EventArgs e) // ReSharper restore InconsistentNaming { Close(); } } }
' ' Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html . ' OPC client and subscriber examples in VB.NET on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-VBNET . ' Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own ' a commercial license in order to use Online Forums, and we reply to every post. Imports System.Globalization Imports JetBrains.Annotations Imports OpcLabs.EasyOpc Imports OpcLabs.EasyOpc.DataAccess Imports OpcLabs.EasyOpc.OperationModel Imports OpcLabs.EasyOpc.DataAccess.OperationModel Partial Public Class Form1 Inherits Form Private Const MachineName As String = "" Private Const ServerClass As String = "SWToolbox.TOPServer.V5" ' or "Kepware.KEPServerEX.V5" Private _fanPower As DAVtq Private _heaterPower As DAVtq Private _ovenTemperature As DAVtq Private _heaterTemperature As DAVtq Private _fanSpeed As DAVtq Private _temperatureSetpoint As DAVtq Public Sub New() InitializeComponent() End Sub Private _defaultBackColor As Color = Color.White ' ReSharper disable InconsistentNaming Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load ' ReSharper restore InconsistentNaming SetDefaults() _defaultBackColor = txbOvenTemperature.BackColor End Sub Private Sub SetDefaults() nudUpdateRate.Value = 10 End Sub ' ReSharper disable InconsistentNaming Private Sub btnStart_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnStart.Click ' ReSharper restore InconsistentNaming btnStart.Enabled = False timer1.Interval = Decimal.ToInt32(nudUpdateRate.Value * 1000) timer1.Start() UpdateValuesAndLog() btnStop.Enabled = True End Sub ' ReSharper disable InconsistentNaming Private Sub btnStop_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnStop.Click ' ReSharper restore InconsistentNaming btnStop.Enabled = False timer1.Stop() btnStart.Enabled = True End Sub ' ReSharper disable InconsistentNaming Private Sub timer1_Tick(ByVal sender As Object, ByVal e As EventArgs) Handles timer1.Tick ' ReSharper restore InconsistentNaming UpdateValuesAndLog() End Sub Private Function ConvertValueToInt32(ByVal vtq As DAVtq) As Int32? If vtq Is Nothing Then Return Nothing End If If Not vtq.HasValue() Then Return Nothing End If Return CType(vtq.Value, Int32?) End Function Private Function GetTextVtq(ByVal vtq As DAVtq) As String If (vtq Is Nothing) OrElse ((Not vtq.HasValue())) Then Return "???" End If Return vtq.DisplayValue() End Function Private Sub DisplayVtq(ByVal vtq As DAVtq, ByVal txb As TextBox, ByVal colorTestId As Integer) If (vtq Is Nothing) OrElse ((Not vtq.HasValue())) Then ' ReSharper disable LocalizableElement txb.Text = "???" ' ReSharper restore LocalizableElement txb.BackColor = Color.Magenta Else txb.Text = vtq.DisplayValue() Dim value? As Int32 Dim aBackColor As Color = _defaultBackColor Select Case colorTestId Case 0 txb.BackColor = _defaultBackColor Case 1 ' oven temperature value = ConvertValueToInt32(vtq) If value.HasValue Then Dim range? As Int32 = ConvertValueToInt32(_temperatureSetpoint) If range.HasValue Then If value <= (range - 5) Then aBackColor = Color.Blue Else If value >= (range + 5) Then aBackColor = Color.Red End If End If End If End If txb.BackColor = aBackColor Case 2 ' oven temperature value = ConvertValueToInt32(vtq) If value.HasValue Then If value < 200 Then aBackColor = Color.Red End If End If txb.BackColor = aBackColor End Select End If End Sub Private Function ReadVtq(ByVal itemId As String) As DAVtq Dim vtq As DAVtq Dim exception As Exception = Nothing Try vtq = easyDAClient1.ReadItem(MachineName, ServerClass, itemId) Catch ex As OpcException exception = ex vtq = Nothing End Try DisplayException(exception) Return vtq End Function Private Function ReadMultipleVtq(ByVal itemIds() As String) As DAVtqResult() Dim results() As DAVtqResult Dim exception As Exception = Nothing Dim itemDescriptors = New DAItemDescriptor(itemIds.Length - 1) {} For i As Integer = 0 To itemIds.Length - 1 Debug.Assert(itemIds(i) IsNot Nothing) itemDescriptors(i) = New DAItemDescriptor(itemIds(i)) Next i Try results = easyDAClient1.ReadMultipleItems(New ServerDescriptor(MachineName, ServerClass), itemDescriptors) Catch ex As OpcException exception = ex results = Nothing End Try DisplayException(exception) Return results End Function Private _lastExceptionMessage As String = "" Private Sub DisplayException(ByVal exception As Exception) 'txbExceptions.Text = exception == null ? "" : exception.GetBaseException().Message; If exception IsNot Nothing Then Dim newMessage As String = String.Format("{0} {1}", Date.Now, exception.GetBaseException().Message) If _lastExceptionMessage <> newMessage Then _lastExceptionMessage = newMessage txbExceptions.AppendText(newMessage & Environment.NewLine) End If End If End Sub Private Sub ReadMultiple() Dim results() As DAVtqResult = ReadMultipleVtq(New String() {"Channel1.Device1.FanPower", "Channel1.Device1.FanSpeed", "Channel1.Device1.HeaterPower", "Channel1.Device1.HeaterTemp", "Channel1.Device1.TempSetPoint", "Channel1.Device1.OvenTemp"}) If results Is Nothing Then Return End If Debug.Assert(results(0) IsNot Nothing) Debug.Assert(results(1) IsNot Nothing) Debug.Assert(results(2) IsNot Nothing) Debug.Assert(results(3) IsNot Nothing) Debug.Assert(results(4) IsNot Nothing) Debug.Assert(results(5) IsNot Nothing) If results(0).Exception Is Nothing Then _fanPower = results(0).Vtq Else _fanPower = Nothing DisplayException(results(0).Exception) End If If results(1).Exception Is Nothing Then _fanSpeed = results(1).Vtq Else _fanSpeed = Nothing DisplayException(results(1).Exception) End If If results(2).Exception Is Nothing Then _heaterPower = results(2).Vtq Else _heaterPower = Nothing DisplayException(results(2).Exception) End If If results(3).Exception Is Nothing Then _heaterTemperature = results(3).Vtq Else _heaterTemperature = Nothing DisplayException(results(3).Exception) End If If results(4).Exception Is Nothing Then _temperatureSetpoint = results(4).Vtq Else _temperatureSetpoint = Nothing DisplayException(results(4).Exception) End If If results(5).Exception Is Nothing Then _ovenTemperature = results(5).Vtq Else _ovenTemperature = Nothing DisplayException(results(5).Exception) End If End Sub Private Sub UpdateValuesAndLog() ' read multiple item ReadMultiple() DisplayVtq(_fanPower, txbFanPower, 0) DisplayVtq(_fanSpeed, txbFanSpeed, 0) DisplayVtq(_heaterPower, txbHeaterPower, 0) DisplayVtq(_heaterTemperature, txbHeaterTemperature, 2) DisplayVtq(_temperatureSetpoint, txbTemperatureSetpoint, 0) DisplayVtq(_ovenTemperature, txbOvenTemperature, 1) WriteToLog() End Sub ' ReSharper disable InconsistentNaming Private Sub btnSetTemperatureSetpoint_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnSetTemperatureSetpoint.Click ' ReSharper restore InconsistentNaming Dim value As Object = txbNewTemperatureSetpoint.Text Dim exception As Exception = Nothing Try easyDAClient1.WriteItemValue(MachineName, ServerClass, "Channel1.Device1.TempSetPoint", value) Catch ex As OpcException exception = ex End Try DisplayException(exception) _temperatureSetpoint = ReadVtq("Channel1.Device1.TempSetPoint") DisplayVtq(_temperatureSetpoint, txbTemperatureSetpoint, 0) DisplayVtq(_ovenTemperature, txbOvenTemperature, 1) End Sub Private Sub WriteToLog() Try Dim sw = New IO.StreamWriter(Application.StartupPath & "\OvenControl.csv", True) sw.WriteLine(Date.Now.ToString(CultureInfo.InvariantCulture) & "," & GetTextVtq(_fanPower) & "," & GetTextVtq(_heaterPower) & "," & GetTextVtq(_ovenTemperature) & "," & GetTextVtq(_heaterTemperature) & "," & GetTextVtq(_fanSpeed) & "," & GetTextVtq(_temperatureSetpoint)) sw.Close() Catch e As Exception DisplayException(e) End Try End Sub ' ReSharper disable InconsistentNaming Private Sub btnClose_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnClose.Click ' ReSharper restore InconsistentNaming Close() End Sub End Class
Copyright © 2004-2024 CODE Consulting and Development, s.r.o., Plzen. All rights reserved.
Documentation Home, Send Documentation Feedback. Technical Support